package com.dream52.pms.base;

import com.alibaba.fastjson.JSON;
import com.dream52.pms.util.GetEntityClassUtil;
import com.dream52.pms.util.RedisUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

@Service
public abstract class MyServiceImpl<T> implements MyService<T> {

	Class clazz = GetEntityClassUtil.getEntityClass(getClass());

	@Autowired
	public MyMapper<T> mapper;
	@Autowired
	private RedisUtil redis;

	public MyMapper<T> getMapper() {
		return mapper;
	}

	public T getById(int key) {
		return this.mapper.selectByPrimaryKey(key);
	}

	public T getByWhere(String whereStr) {

		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();
		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		List<T> list = this.mapper.selectByExample(example);

		if (list != null && list.size() > 0) {
			return list.get(0);
		} else {
			return null;
		}
	}

	public List<T> getListByWhere(String whereStr, String orderStr) {

		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();

		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		if (orderStr != null && orderStr.length() > 0) {
			example.setOrderByClause(orderStr);
		}

		List<T> list = this.mapper.selectByExample(example);

		return list;
	}

	public List<T> getPageListByWhere(String whereStr, int pageno, int pagesize, String orderStr) {

		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();
		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		if (orderStr != null && orderStr.length() > 0) {
			example.setOrderByClause(orderStr);
		}

		RowBounds r = new RowBounds(pageno, pagesize);

		List<T> list = this.mapper.selectByExampleAndRowBounds(example, r);

		return list;
	}

	public PageInfo<T> getPageByWhere(String whereStr, int pageno, int pagesize, String orderStr) {
		PageHelper.startPage(pageno, pagesize);
		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();

		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		if (orderStr != null && orderStr.length() > 0) {
			example.setOrderByClause(orderStr);
		}

		List<T> list = this.mapper.selectByExample(example);
		PageInfo<T> pageInfo = new PageInfo<T>(list);
		PageHelper.clearPage();

		return pageInfo;
	}

	public int getCountByWhere(String whereStr) {
		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();

		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		return this.mapper.selectCountByExample(example);
	}

	public int save(T entity) {
		return this.mapper.insert(entity);
	}

	public int update(T entity) {
		return this.mapper.updateByPrimaryKeySelective(entity);
	}

	public int updateByWhere(T entity, String whereStr) {
		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();

		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		return this.mapper.updateByExampleSelective(entity, criteria);
	}

	public int deleteById(int id) {
		return this.mapper.deleteByPrimaryKey(id);
	}

	public int deleteByWhere(String whereStr) {
		Example example = new Example(clazz);
		Criteria criteria = example.createCriteria();

		if (whereStr != null && whereStr.length() > 0) {
			criteria.andCondition(whereStr);
		}

		return this.mapper.deleteByExample(example);
	}

	/* 缓存相关 */
	public int saveCache(String cacheId, T entity) {
		int i = this.mapper.insert(entity);

		try {
			Method getid = entity.getClass().getDeclaredMethod("getId", null);
			Integer id = (Integer) getid.invoke(entity);

			redis.hset(cacheId, id.toString(), entity);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return i;
	}

	public int saveCacheByUserid(String cacheId, T entity, int userid) {
		int i = this.mapper.insert(entity);

		try {
			Method getid = entity.getClass().getDeclaredMethod("getId", null);
			Integer id = (Integer) getid.invoke(entity);

			redis.hset(cacheId, String.valueOf(userid), entity);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return i;
	}

	public void updateCacheOnly(String cacheId, T entity) {
		// int i = this.mapper.insert(entity);

		try {
			Method getid = entity.getClass().getDeclaredMethod("getId", null);
			Integer id = (Integer) getid.invoke(entity);

			redis.hset(cacheId, id.toString(), entity);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	public void updateCacheOnlyById(String cacheId, int id) {

		redis.hset(cacheId, String.valueOf(id), this.getById(id));

	}

	public void updateCacheByUserid(String cacheId, T entity, int userid) {
		this.update(entity);
		redis.hset(cacheId, String.valueOf(userid), this.getByWhere("status = 1 AND userid = " + userid));
	}

	public int updateCache(String cacheId, T entity) {
		int i = this.mapper.updateByPrimaryKeySelective(entity);

		try {

			Method getid = entity.getClass().getDeclaredMethod("getId", null);
			Integer id = (Integer) getid.invoke(entity);

			entity = this.getById(id);
			redis.hset(cacheId, id.toString(), entity);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return i;
	}

	public void updateCacheByWhereOnly(String cacheId, String where) {

		List<T> list = this.getListByWhere(where, null);
		for (T t : list) {
			this.updateCacheOnly(cacheId, t);
		}

	}

	public int updateCacheByWhere(String cacheId, T entity, String where) {
		int i = this.updateByWhere(entity, where);

		List<T> list = this.getListByWhere(where, null);
		for (T t : list) {
			this.updateCacheOnly(cacheId, t);
		}

		return i;
	}

	public void deleteCacheIds(String cacheId, String idsStr) {

		String[] ids = idsStr.split(",");
		for (String idstr : ids) {
			Integer id = Integer.valueOf(idstr);
			this.deleteCache(cacheId, id);
		}
	}

	public void deleteCache(String cacheId, int id) {
		redis.hdel(cacheId, id);
	}

	public void deleteCacheAll(String cacheId) {
		redis.del(cacheId);
	}

	public int deleteCacheById(String cacheId, int id) {
		redis.hdel(cacheId, id);
		return this.mapper.deleteByPrimaryKey(id);
	}

	public T getCacheById(String cacheId, Integer key) {
		T t = null;
		String redisStr = (String) redis.hget(cacheId, key.toString());
		if (StringUtils.isNotBlank(redisStr)) {
			t = (T) JSON.parseObject(redisStr, clazz);
		} else {
			t = this.mapper.selectByPrimaryKey(key);
			redis.hset(cacheId, key.toString(), t);
		}
		return t;
	}

	public List<T> getCacheListByWhere(String cacheId, String whereStr, String orderStr) {
		List<T> list = null;
		list = (List<T>) this.redis.lGet(cacheId, 0, -1);
		if (list == null || list.toString().equals("") || list.size() == 0) {
			Example example = new Example(clazz);
			Criteria criteria = example.createCriteria();

			if (whereStr != null && whereStr.length() > 0) {
				criteria.andCondition(whereStr);
			}

			if (orderStr != null && orderStr.length() > 0) {
				example.setOrderByClause(orderStr);
			}

			list = this.mapper.selectByExample(example);
			this.redis.lSet(cacheId, JSON.parseArray(JSON.toJSONString(list), clazz));
		}

		return list;
	}
	/* END */
}
